#include "Avalon/IO/BufferReader.hpp"
#include "Avalon/IO/EndOfFileException.hpp"

using namespace Avalon;
using namespace Avalon::IO;
using namespace Avalon::Threading;
using namespace std;

BufferReader::BufferReader(const Buffer& source)
    : m_source(source),
      m_readIterator(m_source.GetData()),
      m_readRemaining(m_source.GetSize()) {}

BufferReader::~BufferReader() {}

void BufferReader::Read(Buffer* destination, Out<Async<int> > sizeRead) {
  if(m_readRemaining == 0) {
    sizeRead->SetException(EndOfFileException());
    return;
  }
  destination->Append(m_readIterator, m_readRemaining);
  int result = m_readRemaining;
  m_readRemaining = 0;
  sizeRead->SetResult(result);
}

void BufferReader::Read(void* destination, int size,
    Out<Async<int> > sizeRead) {
  if(m_readRemaining == 0) {
    sizeRead->SetException(EndOfFileException());
    return;
  }
  int result = min(size, m_readRemaining);
  memcpy(destination, m_readIterator, result);
  m_readRemaining -= result;
  m_readIterator += result;
  sizeRead->SetResult(result);
}

void BufferReader::Read(Buffer* destination, int size,
    Out<Async<int> > sizeRead) {
  if(m_readRemaining == 0) {
    sizeRead->SetException(EndOfFileException());
    return;
  }
  int result = min(m_readRemaining, size);
  destination->Append(m_readIterator, result);
  m_readIterator += result;
  m_readRemaining -= result;
  sizeRead->SetResult(result);
}
